﻿#include <learn/ais/ais_surface.h>
#include <learn/alg/alg_projection.h>

using namespace xi;
using namespace xi::ais;
using namespace xi::alg;

AIS_Surface::AIS_Surface(std::shared_ptr<Geom_Surface<3>> surface)
    : m_surface(surface), m_sampler(new Alg_Uniform_Sampler)
{
    this->m_collisionFunc = [&](AIS_MouseMsg *msg) -> bool {
        return false;

        // 获得屏幕点和鼠标位置
        Vec2f p = msg->move;
        Vec3 emit = convert<double>(msg->emit(p)).normalize();
        Vec3 P = convert<double>(msg->toSpace(p));

        auto [U1, U2, V1, V2] = m_surface->bounds();
        auto uv = Alg_Projection<3>::parallel(m_surface, P, emit, (U1 + U2) / 2, (V1 + V2) / 2, 1e-2);

        // 如果小于指定深度，则记录下来
        auto Q = m_surface->value(uv.x(), uv.y());
        if (Q.z() < msg->depth && cross((P - Q).normalize(), emit).modulus() < 1e-2)
        {
            msg->depth = Q.z();
            msg->obj = this;
            return true;
        }
        return false;
    };
}

std::shared_ptr<Geom_Surface<3>> AIS_Surface::surface() const
{
    return m_surface;
}

Mesh_Data AIS_Surface::sample(std::size_t num) const
{
    // 修改采样器的采样数量
    auto sampler = std::static_pointer_cast<Alg_Uniform_Sampler>(m_sampler);
    sampler->uCount = num;
    sampler->vCount = num;

    auto [u1, u2, v1, v2] = m_surface->bounds();
    auto samples = sampler->perform(u1, u2, v1, v2);
    std::vector<Vec3f> points(samples.size());
    for (std::size_t i = 0; i < samples.size(); ++i)
        points[i] = convert<float>(m_surface->value(samples[i].x(), samples[i].y()));

    Mesh_Data mesh;
    mesh->vertices.reserve(samples.size());
    mesh->normals.reserve(samples.size());
    mesh->texcoords.reserve(samples.size());
    for (std::size_t i = 0; i < num; ++i)
    {
        for (std::size_t j = 0; j < num; ++j)
        {
            std::size_t idx = i * num + j;

            auto [P, DU, DV] = m_surface->d1(samples[idx].x(), samples[idx].y());
            mesh->vertices.emplace_back(convert<float>(P));
            mesh->normals.emplace_back(convert<float>(cross(DU, DV)));
            mesh->texcoords.emplace_back(float(samples[idx].x()), float(samples[idx].y()));
        }
    }

    mesh->indices.reserve((num - 1) * (num - 1) * 2);
    for (std::size_t i = 0; i < num - 1; ++i)
    {
        for (std::size_t j = 0; j < num - 1; ++j)
        {
            std::size_t idx = i * num + j;
            mesh->indices.emplace_back(idx);
            mesh->indices.emplace_back(idx + num);
            mesh->indices.emplace_back(idx + 1);

            mesh->indices.emplace_back(idx + num);
            mesh->indices.emplace_back(idx + num + 1);
            mesh->indices.emplace_back(idx + 1);
        }
    }

    return mesh;
}

void AIS_Surface::visit(AIS_InitMsg *msg)
{
    // 利用工厂创建渲染器
    if (msg->factory)
        m_renderer.reset(msg->factory->create_product("AIS_Surface"));
}
